/**
 * Facebook-like Slide Show plugin for jQuery Tools
 * Copyright (C) 2012 Eduardo Henrique Leite
 * 
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 * 
 * http://code.google.com/p/fbss/
 */

(function($) {
	$._fbss = {
		conf: {
			/* Percentage of the viewpart that can be used to display the image */
			visibleArea: 0.95,
			/* Object of the viewport to be used by the calculation */
			viewport: $(window),
			/* Selector which holds the container for all images in the slide show */
			items: ".items",
			/* Automatically display first item */
			autoDisplay: false,
			/* Next element class*/
			next: 'next',
			/* Prev element class*/
			prev: 'prev',
			/* Overlay mark*/
			mask: null,
			/* Scrollable selector for integration */
			scrollable: null,
			/* Display the control arrows */
			controls: true,
			
			api: true
		}
	};
	
	/* Constructor */
	function FacebookSlideShow(root, conf) {
		var index = 0,
			usingScrollable = (conf.scrollable != null),
			scrollable = null,
			fire = root.add(this);
			
		if (usingScrollable) {
			scrollable = $(conf.scrollable).data("scrollable");
			if (!scrollable) usingScrollable = false;
		}
		
		$.extend(this, {
			/* Return number of images in the slide show */
			getSize: function() {
				if (usingScrollable) 
					return scrollable.getSize();
				else
					return $(conf.items).children("img").length;
			},
			
			/* Adjust and display an image */
			display: function(i) {
				if (typeof i == "undefined")
					i = 0;
			
				if (i < 0 || i >= this.getSize())
					return this;
					
				index = i;

				this.createOverlay();
				
				fire.trigger("onImageLoaded", [i]);
				
				if (usingScrollable) {
					this.addToOverlay(index);
				}
				else {
					$(conf.items).children("img").hide();
					this.adjustSize($(conf.items).children("img").eq(i));
					this.copyToOverlay($(conf.items).children("img").eq(i));
				}
				
				return this;
			},
			
			/* Add an image from scrollable into the overlay */
			addToOverlay: function(index) {
				if (usingScrollable) {
					var item = scrollable.getItems().eq(index);
					if (item) {
						var html = '<img src="' + item.attr("data") + '" style="display: none" />';
						
						root.children("img").remove();
						root.append(html);
						this.adjustSize(root.children("img").eq(0)).css({
							'display': 'block'
						});
					}
				}
			},
			
			/* Open the overlay displaying the current scrollable item */
			displayCurrent: function() {
				if (usingScrollable) {
					index = scrollable.getIndex();
					this.display(index);
				}
				
				return this;
			},
			
			/* Return current index */
			getIndex: function() {
				return index;
			},
			
			/* Moves slide show to next index */
			next: function() {
				if (index >= this.getSize() - 1) {
					this.display(0);
				}
				else {
					this.display(index + 1);
				}
				
				return this;
			},
			
			/* Moves slide show to previous index */
			prev: function() {
				if (index == 0) {
					this.display(this.getSize() - 1);
				}
				else {
					this.display(index - 1);
				}
				
				return this;
			},
			
			/* Adjust size of an image proportionally based on browser resolution */
			adjustSize: function(image) {
				resetStyle(image);
				
				var imgW = image.width(),
					imgH = image.height(),
					cofW = imgW / conf.viewport.width(),
					cofH = imgH / conf.viewport.height(),
					imgVisibleArea = conf.visibleArea - 0.05;
					
				if (cofW > imgVisibleArea || cofH > imgVisibleArea) {
					if (cofW > cofH) {
						var workW = conf.viewport.width() * imgVisibleArea,
							varW  = workW / imgW;
						
						imgW = workW;
						imgH *= varW;
					}
					else { //cofW <= cofH
						var workH = conf.viewport.height() * imgVisibleArea,
							varH  = workH / imgH;
						
						imgH = workH;
						imgW *= varH;
					}
				}

				this.setImageSize(image, imgW, imgH, conf.viewport.width(), conf.viewport.height());
				this.setOverlaySize(conf.viewport.width() * conf.visibleArea, conf.viewport.height() * conf.visibleArea);
				
				return image;
			},
			
			/* Clone image from items container into the overlay */
			copyToOverlay: function(image) {
				root.children("img").remove();
				image.clone().css({
					'display': 'block'
				}).appendTo(root);
			},
			
			/* Create and/or load the overlay */
			createOverlay: function() {
				if (!$(root).data("overlay")) {
					if (this.getSize() > 1 && conf.controls) {
						this.createUIElements();
					}
					
					root.css({
						'width': (conf.viewport.width() * conf.visibleArea) + 'px',
						'height': (conf.viewport.height() * conf.visibleArea) + 'px'
					});
				
					$(root).overlay({
						top: '2.5%',
						mask: conf.mask,
						load: true
					});
				}
				else {
					$(root).data("overlay").load();
				}
			},
				
			/* Create the control arrows */
			createUIElements: function() {
				var begin = '<a class="',
					end   = '"></a>',
					self  = this;
				
				root.append(begin + conf.prev + end);
				root.append(begin + conf.next + end);
				
				root.children('.' + conf.prev).click(function() {
					self.prev();
				});
				
				root.children('.' + conf.next).click(function() {
					self.next();
				});
			},
			
			setImageSize: function (image, width, height, vpw, vph) {
				var left = parseInt((vpw * conf.visibleArea - width) / 2),
					top  = parseInt((vph * conf.visibleArea - height) / 2);
			
				image.css({
					'width': width + 'px',
					'height': height + 'px',
					'position': 'absolute',
					'left': left + 'px',
					'top': top + 'px'
				});
			},
			
			setOverlaySize: function(width, height) {
				$(root).css({
					'width': width + 'px',
					'height': height + 'px',
				});
			}
		});
		
		// callbacks	
        $.each(['onImageLoaded'], function (i, name) {

            // configuration
            if ($.isFunction(conf[name])) {
                $(self).bind(name, conf[name]);
            }

            self[name] = function (fn) {
                if (fn) { $(self).bind(name, fn); }
                return self;
            };
        });
		
		if (conf.autoDisplay) {
			this.display();
		}
	}
	
	function resetStyle(image) {
		image.attr("style", "");
	}
	
	/* Plugin implementation */
	$.fn.fbss = function(conf) { 
		var el = this.data("ffss");
		if (el) { return el; }		 

		conf = $.extend({}, $._fbss.conf, conf); 
		
		this.each(function() {			
			el = new FacebookSlideShow($(this), conf);
			$(this).data("ffss", el);	
		});
		
		return conf.api ? el : this;
	};
})(jQuery);
